Skip to content

[Android] Properly handle requestDisallowInterceptTouchEvent for v3 - #4367

Open
j-piasecki wants to merge 1 commit into
mainfrom
jpiasecki/handle-request-disallow
Open

[Android] Properly handle requestDisallowInterceptTouchEvent for v3#4367
j-piasecki wants to merge 1 commit into
mainfrom
jpiasecki/handle-request-disallow

Conversation

@j-piasecki

@j-piasecki j-piasecki commented Jul 30, 2026

Copy link
Copy Markdown
Member

Description

On Android, when a native view calls requestDisallowInterceptTouchEvent (e.g. a pager starting a swipe), RNGestureHandlerRootView reacted by cancelling all handlers registered on the root. react-native-pager-view calls it eagerly on touch down, so any v3 gesture rendered inside a pager (e.g. inside material top tabs) was cancelled before it could activate — a long press nested in top tabs never activated at all.

This PR makes the cancellation targeted:

  • The root view now cancels only legacy handlers (v1/v2 action types) via the new GestureHandlerOrchestrator.cancelAllLegacyHandlers, instead of the old trick of activating the internal RootViewGestureHandler. The root handler is now attached with ACTION_TYPE_NONE so it's excluded from that sweep (and no longer sends dead events to JS).
  • v3 handlers are cancelled by new requestDisallowInterceptTouchEvent overrides on RNGestureHandlerDetectorView and ButtonViewGroup. Since the request only bubbles upward from the requesting view, only handlers attached to its ancestors are cancelled — handlers below the requester (like the long press under the pager) keep working.
  • Cancellation is skipped while the orchestrator is delivering events (isHandlingTouch), mirroring the existing passingTouch guard, so disallow requests caused by RNGH's own event delivery don't cancel gestures.
  • findGestureHandlerRootView now returns the nearest enabled root view so the checks above consult the orchestrator that actually manages the subtree.

Test plan

Tested on reproducer from #2383

Screen.Recording.2026-07-31.at.11.38.38.mov

Copilot AI review requested due to automatic review settings July 30, 2026 13:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts Android’s requestDisallowInterceptTouchEvent handling to avoid canceling v3 gestures too broadly (notably inside pagers), by making cancellation more targeted across root/orchestrator and v3 detector/button views.

Changes:

  • Add GestureHandlerOrchestrator.cancelAllLegacyHandlers() and use it from the root helper instead of triggering cancellation via the internal root handler.
  • Override requestDisallowInterceptTouchEvent in v3 host detector and button view to cancel only relevant handlers (and skip cancellation while the orchestrator is handling touch).
  • Update root view lookup to prefer the nearest enabled RNGestureHandlerRootView and expose the orchestrator via the root view/root helper.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt Exposes orchestrator and returns nearest enabled GH root view when searching ancestors.
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt Switches root-level cancellation to cancelAllLegacyHandlers and attaches root handler with ACTION_TYPE_NONE.
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerDetectorView.kt Adds requestDisallowInterceptTouchEvent override to cancel v3 handlers attached via the host detector.
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt Adds requestDisallowInterceptTouchEvent override to cancel the button’s managed v3 handler.
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt Introduces cancelAllLegacyHandlers() to selectively cancel v1/v2 action types.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@j-piasecki
j-piasecki force-pushed the jpiasecki/handle-request-disallow branch 2 times, most recently from 3c9f4bc to 934af71 Compare July 31, 2026 09:14
@j-piasecki
j-piasecki force-pushed the jpiasecki/handle-request-disallow branch from 934af71 to c30a19c Compare July 31, 2026 09:25
@j-piasecki
j-piasecki marked this pull request as ready for review July 31, 2026 11:34
Comment on lines +58 to +67
val currentHandlers = attachedHandlers.mapNotNull { tag ->
RNGestureHandlerModule.registries[this.moduleId]?.getHandler(tag)
}.filter {
// The handler has been recorded
it.view != null
}

currentHandlers.forEach {
it.cancel()
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we do it simpler?

Suggested change
val currentHandlers = attachedHandlers.mapNotNull { tag ->
RNGestureHandlerModule.registries[this.moduleId]?.getHandler(tag)
}.filter {
// The handler has been recorded
it.view != null
}
currentHandlers.forEach {
it.cancel()
}
val registry = RNGestureHandlerModule.registries[moduleId] ?: return
for (tag in attachedHandlers) {
registry.getHandler(tag)?.takeIf { it.view != null }?.cancel()
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants